<!--
 * @Author: zengwj
 * @Date: 2022-06-17 16:10:55
 * @LastEditors: zengwj
 * @LastEditTime: 2022-09-21 17:26:47
 * @Description: 
-->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    // 三种状态 初始pengding 一旦改变 不可更改
    const PENDING = 'pengding'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    // 本质上是回调函数调用和触发
    class MyPromise {
      value = ''
      status = PENDING
      fulfilledCallbacks = []
      rejectedCallbacks = []
      constructor(executor) {
        // executor 是一个执行器，进入会立即执行
        // 并传入resolve和reject方法 bind 绑定this 指向
        try {
          executor(this.resolve.bind(this), this.reject.bind(this))
        } catch (error) {
          this.reject(error)
        }
      }
      resolve(value) {
        if (this.status === PENDING) {
          this.status = FULFILLED
          this.value = value
          this.fulfilledCallbacks.forEach(callback => {
            callback(value)
          })
        }
      }
      reject(reason) {
        if (this.status === PENDING) {
          this.status = REJECTED
          this.value = reason
          this.rejectedCallbacks.forEach(callback => {
            callback(reason)
          })
        }
      }
      //返回一个新的promise 对象 实现链式调用 then是一个微任务 用queueMicrotask实现，原生 new pronise().then也是用这个api
      then(fulfilled, rejected) {
        const realOnFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
        const realOnRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };

        const Promise2 = new MyPromise((resolve, reject) => {
          const fulfilledMicrotask = () => {
            queueMicrotask(() => {
              const x = realOnFulfilled(this.value)
              resolvePromise(x, resolve, reject)
            })
          }
          const rejectedMicrotask = () => {
            queueMicrotask(() => {
              const x = realOnRejected(this.value)
              resolvePromise(x, resolve, reject)
            })
          }
          if (this.status === PENDING) {
            // 等待
            // 因为不知道后面状态的变化情况，所以将成功回调和失败回调存储起来
            // 等到执行成功失败函数的时候再传递
            this.fulfilledCallbacks.push(fulfilledMicrotask)
            this.rejectedCallbacks.push(rejectedMicrotask)
          } else if (this.status === FULFILLED) {
            fulfilledMicrotask()
          } else if (this.status === REJECTED) {
            rejectedMicrotask()
          }
        })
        return Promise2
      }
      static resolve(value) {
        //如果是一个promise 返回
        if (value instanceof MyPromise) {
          return value
        }
        return new MyPromise((resolve) => {
          resolve(value)
        })
      }
      //创建一个promise实现
      static all(promises) {
        const allPromise = new MyPromise((resolve, reject) => {
          if (Array.isArray(promises)) {
            const result = []
            let count = 0
            if (promises.length === 0) {
              return resolve(promises)
            }
            promises.forEach((item, index) => {
              if (item instanceof MyPromise) {
                item.then((value) => {
                  result[index] = value
                  count++
                  count === promises.length && (resolve(result))
                }, (reason) => {
                  reject(reason)
                })
              }
              // 返回值直接加入result 结果
              else {
                result[index] = item
                count++
                count === promises.length && (resolve(result))
              }
            })
          } else {
            reject(new TypeError('fuck you 参数不对'))
          }
        })
        return allPromise
      }
      static race(Promises) {
        return new MyPromise((resolve, reject) => {
          if (Array.isArray(promises)) {
            if (promises.length > 0) {
              promises.forEach(item => {
                item.then(resolve, reject)
              })
            }
          } else {
            reject(new TypeError('fuck you 参数不对'))
          }
        })
      }
      finally(callback) {
        return this.then(callback, callback)
      }
      catch(callback) {
        return this.then(undefined, callback)
      }
    }
    function resolvePromise(x, resolve, reject) {
      //x 如果是实例对象
      if (x instanceof MyPromise) {
        x.then(resolve, reject)
      } else {
        resolve(x)
      }
    }
    const promise1 = MyPromise.resolve(3);
    const promise2 = 42;
    const promise3 = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        resolve('foo')
      }, 100);
    })

    const ppppp = new MyPromise((resolve) => {

    })
    console.log(ppppp)
    debugger

    MyPromise.all([promise1, promise2, promise3]).then((values) => {
      console.log(values);
    }, (reason) => {
      console.log(reason)
    }).catch((error) => {
      console.log(error)
    });
  </script>
</body>

</html>